<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring MVC异常处理机制解析</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .code-block {
            background-color: #2d2d2d;
            color: #f8f8f2;
            border-radius: 0.5rem;
            font-family: 'Courier New', monospace;
        }
        .method-card:hover {
            transform: translateY(-4px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .hover-underline:hover {
            text-decoration: underline;
            text-decoration-color: #667eea;
        }
        .drop-cap::first-letter {
            font-size: 4em;
            float: left;
            line-height: 0.8;
            margin: 0.1em 0.1em 0.1em 0;
            color: #667eea;
            font-weight: bold;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 px-4 md:px-0">
        <div class="container mx-auto max-w-5xl text-center">
            <h1 class="text-4xl md:text-5xl font-bold mb-6 font-serif">Spring MVC异常处理全指南</h1>
            <p class="text-xl md:text-2xl mb-8 max-w-3xl mx-auto leading-relaxed">
                掌握6种核心异常处理机制，构建健壮的Spring应用程序
            </p>
            <div class="flex justify-center space-x-4">
                <a href="#methods" class="bg-white text-indigo-700 hover:bg-gray-100 px-6 py-3 rounded-full font-semibold transition duration-300">
                    <i class="fas fa-book mr-2"></i>学习技巧
                </a>
                <a href="#visualization" class="bg-indigo-800 hover:bg-indigo-900 text-white px-6 py-3 rounded-full font-semibold transition duration-300">
                    <i class="fas fa-project-diagram mr-2"></i>查看图表
                </a>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <main class="container mx-auto max-w-5xl px-4 py-12">
        <!-- Introduction -->
        <section class="mb-16">
            <p class="drop-cap text-lg md:text-xl text-gray-700 mb-6">
                在Spring MVC中，处理异常有多种方式。Spring提供了一些强大的机制来捕获和处理控制器方法中的异常，以便提供用户友好的错误信息和执行适当的恢复操作。
            </p>
            <p class="text-lg md:text-xl text-gray-700 mb-6">
                通过合理配置异常处理机制，可以提供用户友好的错误提示，并有效地管理应用程序的异常处理逻辑。本文将详细介绍6种核心异常处理方式，帮助您构建更健壮的Spring应用程序。
            </p>
        </section>

        <!-- Methods Section -->
        <section id="methods" class="mb-20">
            <h2 class="text-3xl font-bold mb-8 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-cogs mr-3 text-indigo-600"></i>异常处理方法详解
            </h2>

            <!-- Method 1 -->
            <div class="method-card bg-white rounded-xl shadow-md overflow-hidden mb-8 transition duration-300">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 rounded-full w-10 h-10 flex items-center justify-center mr-4">
                            <span class="font-bold">1</span>
                        </div>
                        <h3 class="text-2xl font-bold text-gray-800">@ExceptionHandler 注解</h3>
                    </div>
                    <p class="text-gray-600 mb-4">
                        允许你在控制器中定义一个方法来处理特定的异常。这种方法通常用于处理控制器方法中的异常，并返回自定义的错误响应。
                    </p>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@Controller
public class MyController {

    @RequestMapping("/hello")
    public String hello() {
        // 可能会抛出异常的代码
        throw new RuntimeException("Something went wrong");
    }

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity&lt;String&gt; handleRuntimeException(RuntimeException e) {
        // 返回自定义的错误响应
        return new ResponseEntity&lt;&gt;("Custom error message: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}</code></pre>
                    </div>
                    <div class="flex items-center text-sm text-gray-500">
                        <i class="fas fa-info-circle mr-2 text-indigo-500"></i>
                        <span>适用于控制器内部的局部异常处理</span>
                    </div>
                </div>
            </div>

            <!-- Method 2 -->
            <div class="method-card bg-white rounded-xl shadow-md overflow-hidden mb-8 transition duration-300">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 rounded-full w-10 h-10 flex items-center justify-center mr-4">
                            <span class="font-bold">2</span>
                        </div>
                        <h3 class="text-2xl font-bold text-gray-800">@ControllerAdvice 注解</h3>
                    </div>
                    <p class="text-gray-600 mb-4">
                        用于集中处理控制器异常的类。通过在类上使用@ControllerAdvice注解，可以定义全局的异常处理逻辑。它允许你定义全局的异常处理器，可以在不同的控制器中共享。
                    </p>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity&lt;String&gt; handleRuntimeException(RuntimeException e) {
        return new ResponseEntity&lt;&gt;("Global handler: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity&lt;String&gt; handleException(Exception e) {
        return new ResponseEntity&lt;&gt;("Global handler for exception: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}</code></pre>
                    </div>
                    <div class="flex items-center text-sm text-gray-500">
                        <i class="fas fa-globe mr-2 text-indigo-500"></i>
                        <span>适用于整个应用的全局异常处理</span>
                    </div>
                </div>
            </div>

            <!-- Method 3 -->
            <div class="method-card bg-white rounded-xl shadow-md overflow-hidden mb-8 transition duration-300">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 rounded-full w-10 h-10 flex items-center justify-center mr-4">
                            <span class="font-bold">3</span>
                        </div>
                        <h3 class="text-2xl font-bold text-gray-800">ResponseEntityExceptionHandler</h3>
                    </div>
                    <p class="text-gray-600 mb-4">
                        Spring提供的一个基类，它允许你处理Spring MVC中的标准异常，如MethodArgumentNotValidException、HttpMediaTypeNotSupportedException等。继承ResponseEntityExceptionHandler并重写相关方法，可以集中处理这些标准异常。
                    </p>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity&lt;Object&gt; handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // 自定义处理逻辑
        return new ResponseEntity&lt;&gt;("Validation failed", HttpStatus.BAD_REQUEST);
    }

    @Override
    protected ResponseEntity&lt;Object&gt; handleHttpMediaTypeNotSupported(
            HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // 自定义处理逻辑
        return new ResponseEntity&lt;&gt;("Unsupported media type", HttpStatus.UNSUPPORTED_MEDIA_TYPE);
    }
}</code></pre>
                    </div>
                    <div class="flex items-center text-sm text-gray-500">
                        <i class="fas fa-shield-alt mr-2 text-indigo-500"></i>
                        <span>特别适合处理Spring内置的标准异常</span>
                    </div>
                </div>
            </div>

            <!-- Method 4 -->
            <div class="method-card bg-white rounded-xl shadow-md overflow-hidden mb-8 transition duration-300">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 rounded-full w-10 h-10 flex items-center justify-center mr-4">
                            <span class="font-bold">4</span>
                        </div>
                        <h3 class="text-2xl font-bold text-gray-800">@ResponseStatus 注解</h3>
                    </div>
                    <p class="text-gray-600 mb-4">
                        可以直接在自定义异常类上使用，用于指定HTTP响应状态码。这样，当该异常被抛出时，Spring会自动返回相应的状态码。
                    </p>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}</code></pre>
                    </div>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@Controller
public class MyController {
    @RequestMapping("/hello")
    public String hello() {
        throw new ResourceNotFoundException("Resource not found");
    }
}</code></pre>
                    </div>
                    <div class="flex items-center text-sm text-gray-500">
                        <i class="fas fa-tag mr-2 text-indigo-500"></i>
                        <span>为自定义异常预定义HTTP状态码</span>
                    </div>
                </div>
            </div>

            <!-- Method 5 -->
            <div class="method-card bg-white rounded-xl shadow-md overflow-hidden mb-8 transition duration-300">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 rounded-full w-10 h-10 flex items-center justify-center mr-4">
                            <span class="font-bold">5</span>
                        </div>
                        <h3 class="text-2xl font-bold text-gray-800">@ExceptionHandler和@ControllerAdvice的结合</h3>
                    </div>
                    <p class="text-gray-600 mb-4">
                        结合@ExceptionHandler和@ControllerAdvice可以实现更灵活和集中化的异常处理。在@ControllerAdvice中定义全局异常处理方法，同时可以在特定的控制器中使用@ExceptionHandler定义局部异常处理。
                    </p>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity&lt;String&gt; handleResourceNotFound(ResourceNotFoundException e) {
        return new ResponseEntity&lt;&gt;(e.getMessage(), HttpStatus.NOT_FOUND);
    }
}</code></pre>
                    </div>
                    <div class="flex items-center text-sm text-gray-500">
                        <i class="fas fa-puzzle-piece mr-2 text-indigo-500"></i>
                        <span>灵活组合局部与全局异常处理</span>
                    </div>
                </div>
            </div>

            <!-- Method 6 -->
            <div class="method-card bg-white rounded-xl shadow-md overflow-hidden mb-8 transition duration-300">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 text-indigo-800 rounded-full w-10 h-10 flex items-center justify-center mr-4">
                            <span class="font-bold">6</span>
                        </div>
                        <h3 class="text-2xl font-bold text-gray-800">处理异常并返回视图</h3>
                    </div>
                    <p class="text-gray-600 mb-4">
                        如果需要在Web应用中处理异常并返回特定的错误页面，可以在@ControllerAdvice中定义一个方法，返回一个视图名称。
                    </p>
                    <div class="code-block p-4 mb-4 overflow-x-auto">
                        <pre><code class="text-sm">@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e, Model model) {
        model.addAttribute("error", e.getMessage());
        return "error"; // 返回错误页面视图
    }
}</code></pre>
                    </div>
                    <div class="flex items-center text-sm text-gray-500">
                        <i class="fas fa-file-alt mr-2 text-indigo-500"></i>
                        <span>适用于传统的Web应用错误页面展示</span>
                    </div>
                </div>
            </div>
        </section>

        <!-- Visualization Section -->
        <section id="visualization" class="mb-20">
            <h2 class="text-3xl font-bold mb-8 text-gray-800 border-b pb-2 flex items-center">
                <i class="fas fa-project-diagram mr-3 text-indigo-600"></i>异常处理机制关系图
            </h2>
            <div class="bg-white rounded-xl shadow-md p-6">
                <div class="mermaid">
                    graph TD
                    A[Spring MVC异常处理] --> B[@ExceptionHandler]
                    A --> C[@ControllerAdvice]
                    A --> D[ResponseEntityExceptionHandler]
                    A --> E[@ResponseStatus]
                    C --> F[全局异常处理]
                    B --> G[局部异常处理]
                    D --> H[标准异常处理]
                    E --> I[自定义异常状态码]
                    F --> J[返回ResponseEntity]
                    F --> K[返回错误视图]
                    G --> J
                    style A fill:#667eea,color:#fff
                    style B fill:#764ba2,color:#fff
                    style C fill:#764ba2,color:#fff
                    style D fill:#764ba2,color:#fff
                    style E fill:#764ba2,color:#fff
                    style F fill:#9f7aea,color:#fff
                    style G fill:#9f7aea,color:#fff
                    style H fill:#9f7aea,color:#fff
                    style I fill:#9f7aea,color:#fff
                    style J fill:#d6bcfa,color:#000
                    style K fill:#d6bcfa,color:#000
                </div>
            </div>
        </section>

        <!-- Summary Section -->
        <section class="bg-indigo-50 rounded-xl p-8 mb-12">
            <h2 class="text-2xl font-bold mb-6 text-indigo-800 flex items-center">
                <i class="fas fa-lightbulb mr-3"></i>关键要点总结
            </h2>
            <ul class="space-y-4">
                <li class="flex items-start">
                    <i class="fas fa-check-circle text-indigo-600 mt-1 mr-3"></i>
                    <span><strong>@ExceptionHandler</strong> - 最适合处理控制器特定的异常</span>
                </li>
                <li class="flex items-start">
                    <i class="fas fa-check-circle text-indigo-600 mt-1 mr-3"></i>
                    <span><strong>@ControllerAdvice</strong> - 实现全局异常处理的最佳选择</span>
                </li>
                <li class="flex items-start">
                    <i class="fas fa-check-circle text-indigo-600 mt-1 mr-3"></i>
                    <span><strong>ResponseEntityExceptionHandler</strong> - 处理Spring标准异常的基类</span>
                </li>
                <li class="flex items-start">
                    <i class="fas fa-check-circle text-indigo-600 mt-1 mr-3"></i>
                    <span><strong>@ResponseStatus</strong> - 为自定义异常预定义HTTP状态码</span>
                </li>
                <li class="flex items-start">
                    <i class="fas fa-check-circle text-indigo-600 mt-1 mr-3"></i>
                    <span>组合使用这些技术可以实现<strong>灵活而强大</strong>的异常处理系统</span>
                </li>
            </ul>
        </section>
    </main>

    <!-- Footer -->
    <footer class="bg-gray-900 text-gray-300 py-8">
        <div class="container mx-auto max-w-5xl px-4">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-4 md:mb-0">
                    <h3 class="text-xl font-bold text-white mb-2">技术小馆</h3>
                    <a href="http://www.yuque.com/jtostring" class="hover-underline hover:text-white transition duration-300">http://www.yuque.com/jtostring</a>
                </div>
                <div class="flex space-x-4">
                    <a href="#" class="text-gray-400 hover:text-white transition duration-300">
                        <i class="fab fa-github text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-400 hover:text-white transition duration-300">
                        <i class="fab fa-twitter text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-400 hover:text-white transition duration-300">
                        <i class="fab fa-linkedin text-xl"></i>
                    </a>
                </div>
            </div>
            <div class="border-t border-gray-800 mt-8 pt-8 text-center text-sm text-gray-500">
                &copy; 2023 技术小馆. All rights reserved.
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>